using System;
using System.Collections.Generic;
using SharpDropBoxClient;

namespace System.IO.DropBox
{
    public class DBXFile
    {
        private static IDropBoxSetup _DropBoxSetupObject = DropBoxSetup.Instance;

        public static IDropBoxSetup DropBoxSetupObject
        {
            get
            {
                return _DropBoxSetupObject;
            }
            set
            {
                _DropBoxSetupObject = value;
                DBXDirectory.setDropBoxSetupObjectFromFile(value);
            }
        }

        internal static void setDropBoxSetupObjectFromDirectory(IDropBoxSetup dropBoxSetupObject)
        {
            _DropBoxSetupObject = dropBoxSetupObject;
        }

        private static IDropBoxApp DbxApp
        {
            get
            {
                if (DropBoxSetupObject == null)
                    return null;
                return DropBoxSetupObject.DropBoxApp;
            }
        }

        private static bool EnsureDbxAppHasInstance(Action<Exception> errorCallback)
        {
            if (DbxApp == null)
            {
                errorCallback(new IOException("You need to configure the DropBoxSetup object first"));
                return false;
            }
            return true;
        }

        public static void AppendTextAsync(string path)
        {
        }

        public static void Copy(string sourceFileName, string destFileName)
        {
        }

        public static void Copy(string sourceFileName, string destFileName, bool overwrite)
        {
        }

        //public static DBXResultWithCompletionFunction<StreamWriter> Create(string path, Action<DBoxListing, Exception> completeCallback)
        //{
        //    var memStream = new MemoryStream();
        //    var result = new DBXResultWithCompletionFunction<Stream>(new StreamWriter(memStream), (obj) =>
        //    {
        //        DbxApp.UploadFile(path, )
        //    });
        //}

        //public static DBXResultWithCompletionFunction<FileStream> Create(string path, int bufferSize)
        //{
        //    throw new NotImplementedException();
        //}

        //public static DBXResultWithCompletionFunction<StreamWriter> CreateText(string path)
        //{
        //    throw new NotImplementedException();
        //}

        public static void Delete(string path)
        {
            throw new NotImplementedException();
        }

        public static bool Exists(string path)
        {
            throw new NotImplementedException();
        }

        public static DateTime GetCreationTime(string path)
        {
            throw new NotImplementedException();
        }

        public static DateTime GetLastAccessTime(string path)
        {
            throw new NotImplementedException();
        }

        public static DateTime GetLastWriteTime(string path)
        {
            throw new NotImplementedException();
        }

        public static void Move(string sourceFileName, string destFileName)
        {
            throw new NotImplementedException();
        }

        public static DBXResultWithCompletionFunction<FileStream> Open(string path, FileMode mode)
        {
            throw new NotImplementedException();
        }

        public static DBXResultWithCompletionFunction<FileStream> Open(string path, FileMode mode, FileAccess access)
        {
            throw new NotImplementedException();
        }

        public static DBXResultWithCompletionFunction<FileStream> Open(string path, FileMode mode, FileAccess access, FileShare share)
        {
            throw new NotImplementedException();
        }

        public static DBXResultWithCompletionFunction<FileStream> OpenRead(string path)
        {
            throw new NotImplementedException();
        }

        //public static DBXResultWithCompletionFunction<StreamReader> OpenText(string path)
        //{
        //    throw new NotImplementedException();
        //}

        public static DBXResultWithCompletionFunction<FileStream> OpenWrite(string path)
        {
            throw new NotImplementedException();
        }

        public static void SetAttributes(string path, FileAttributes fileAttributes)
        {
            return;
        }

        public static void SetAttributesAsync(string path, FileAttributes fileAttributes, Action<Exception> callback)
        {
            callback(null);
        }

        public static long FileLength(string path)
        {
            if (MetaCache.ContainsKey(path))
            {
                //if(!MetaCache[path].IsDirectory)
                return MetaCache[path].SizeInBytes;
            }
            throw new IOException("Value Not Available in Cache");
        }

        public static void FileLengthAsync(string path, Action<long, Exception> callback)
        {
            if (MetaCache.ContainsKey(path))
            {
                callback(MetaCache[path].SizeInBytes, null);
                return;
            }
            GetDbxDirInfo(path, (listing, ex) =>
            {
                if (ex != null)
                {
                    callback(-1, ex);
                }
                else
                {
                    callback(listing.SizeInBytes, null);
                }
            });
        }

        public static void WriteAllBytes(string path, byte[] bytes)
        {
        }

        internal static Dictionary<string, DBoxListing> metacache = new Dictionary<string, DBoxListing>();

        public static Dictionary<string, DBoxListing> MetaCache
        {
            get
            {
                return metacache;
            }
        }

        internal static void ClearCacheItem(string path)
        {
            if (MetaCache.ContainsKey(path))
            {
                MetaCache.Remove(path);
            }
        }

        internal static void GetDbxDirInfo(string path, Action<DBoxListing, Exception> callback)
        {
            if (MetaCache.ContainsKey(path))
            {
                callback(MetaCache[path], null);
                return;
            }

            if (EnsureDbxAppHasInstance((ex) => callback(null, ex)))
            {
                DbxApp.GetFileEntry(path, new Collections.Generic.List<string>(), (result) =>
                    {
                        if (result.Error != null)
                        {
                            callback(null, result.Error);
                        }
                        else
                        {
                            MetaCache[path] = result.DirInfo;
                            callback(result.DirInfo, null);
                        }
                    });
            }
        }
    }
}